//unscoped enums
enum Color {red, white, black};

//scopted enums
enum class Color_s {red_s, white_s, black_s};

void tc1_namePollution()
{
	//unscoped enums are in same scope as the enum ifself
	Color c = red;

	//bool red = true;		//name 'red' can not be used for other purpose. 

	Color_s c_s = Color_s::red_s;	// red_s is inside Color_s. 
	bool red_s = true;		//name 'red_s' is still available for using
}

void tc2_scopedEnumsIsStronglyTyped()
{
	int colornumber = red;
	//colornumber = Color_s::red_s;  //error, Color_s::red_s is not a int. 
	colornumber = static_cast<int>(Color_s::red_s);		//this is the valid way to cast. 
}

// In C++ 11, unscoped Enums also support to define underlying type
enum class TC3_ENUM1 { ITEM1, ITEM2, ITEM3 };
enum class TC3_ENUM2 : short { ITEM1, ITEM2, ITEM3 };
void tc3_underlyingType()
{
	auto s = sizeof(TC3_ENUM1::ITEM1);		// s is 4
	s = sizeof(TC3_ENUM2::ITEM1);			// s is 2

	//because of this, forward declaration is possible for unscoped Enums
	//for sure, it is always possible for scoped enums. 
}

#include <tuple>
#include <string>
enum TC4_TYPES1 { tc4_name, tc4_age, tc4_gender };
enum class TC4_TYPES2 { tc4_name, tc4_age, tc4_gender };
using TC4_UserInfo = std::tuple < std::string, int, std::string > ;

/*
constexpr has not been supported by visual studio 2013

template<typename E>
constexpr std::size_t toIndex(E enumerator)
{
	return static_cast<std::size_t>(enumerator);
}
*/

void tc4_oneGoodThingAboutUnscopedEnums()
{
	TC4_UserInfo userInfo{ "John", 40, "Male" };

	//unscoped enums give you simple code
	auto val1 = std::get<0>(userInfo);
	auto val2 = std::get<tc4_name>(userInfo);

	//scoped enums is more code but more right
	auto val3 = std::get<static_cast<std::size_t>(TC4_TYPES2::tc4_name)>(userInfo);	
	//auto val4 = std::get<toIndex(TC4_TYPES2::tc4_name)>(userInfo);
}

int Test_I10_PreferScopedEnumsToUnscoped(int, char**)
{
	tc1_namePollution();
	tc2_scopedEnumsIsStronglyTyped();
	tc3_underlyingType();
	tc4_oneGoodThingAboutUnscopedEnums();

	return 0;
}

/*
Things to Remember
- C++98-style enums are now known as unscoped enums.
- Enumerators of scoped enums are visible only within the enum. They convert to
  other types only with a cast.
- Both scoped and unscoped enums support specification of the underlying type.
  The default underlying type for scoped enums is int. Unscoped enums have no
  default underlying type.
- Scoped enums may always be forward-declared. Unscoped enums may be forward 
  declared only if their declaration specifies an underlying type.
*/